package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.ariticle.IArticleClient;
import com.heima.audit.aliyun.GreenImageScan;
import com.heima.audit.aliyun.GreenTextScan;
import com.heima.audit.tess4j.Tess4jClient;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.redis.CacheService;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.*;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.service.*;
import com.heima.wemedia.util.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author itheima
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmMaterialService wmMaterialService;

    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FileStorageService fileStorageService;


    @Autowired
    private IArticleClient iArticleClient;

    @Autowired
    private ExecutorService executorService;


    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;


    @Autowired
    private CacheService cacheService;
    @Autowired
    private Tess4jClient tess4jClient;
    @Autowired
    private WmUserService wmUserService;
    @Autowired
    private WmChannelService wmChannelService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private WmNewsTaskService wmNewsTaskService;

    @Transactional
    @Override
    public void submit(WmNewsDto wmNewsDto) {
        //判断是都是更新
        Integer id = wmNewsDto.getId();

        //标志位是否是更新
        boolean uFlag = false;
        if (id!=null){
            uFlag =true;
        }

        //先创建一个wmNews将DTo中的属性赋值到里面
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(wmNewsDto,wmNews);
        //去处理useid
        wmNews.setUserId(ThreadLocalUtil.get());
        wmNews.setType(wmNewsDto.getType().shortValue());

        //保存文章中所有的图片的set
        HashSet<String> imageAllSet = new HashSet();

        //保存文章中所有的文本
        List<String> textAllList = new ArrayList<>();
        textAllList.add(wmNews.getTitle());

        //处理状态
        wmNews.setStatus(wmNewsDto.getStatus().shortValue());
        if (wmNews.getStatus()==0){
            wmNews.setReason("草稿");
        }else {
            wmNews.setReason("已提交等待审核");
        }

        //去处理时间
        if (!uFlag){

            //不是更新
            if (wmNewsDto.getStatus()==1){
                //第一次提交就是正式提交
                wmNews.setCreatedTime(new Date());
                wmNews.setSubmitedTime(new Date());
            }else {
                //第一次提交以草稿提交
                wmNews.setCreatedTime(new Date());
            }

        }else {
            //是更新
            if (wmNewsDto.getStatus()==1){
                //更新提交
                wmNews.setSubmitedTime(new Date());
            }

        }


        //处理content
        String content = wmNewsDto.getContent();
        JSONArray contentList = JSON.parseArray(content);

        ArrayList<String> imageUrlList = new ArrayList<>();
        Map mapkey=null;
        for (Object o : contentList) {
            Map map= (Map) o;
            String type = (String) map.get("type");
            if ("image".equals(type)){
                //获取Content中的文件连接
                imageUrlList.add((String) map.get("value"));
            }else {
                if (!map.containsValue("请在这里输入正文")) {
                    //获取所有内容的文本数据
                    textAllList.add(map.get("value").toString());
                }else {
                    mapkey=map;
                }
            }
        }
        if (mapkey!=null){
            contentList.remove(mapkey);
        }
        imageAllSet.addAll(imageUrlList);

        //去处理images
        if (uFlag){
            //如果是更新news相关的中间表数据删除
            LambdaQueryWrapper<WmNewsMaterial> wmNewsMaterialLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wmNewsMaterialLambdaQueryWrapper.eq(WmNewsMaterial::getNewsId,wmNews.getId());
            wmNewsMaterialService.remove(wmNewsMaterialLambdaQueryWrapper);
        }
        //不管更不更新都要重新去写入中间表
        Integer type = wmNewsDto.getType();
        List<String> imageHreadList =null;
        if (type==1){
            //单图
            imageHreadList = wmNewsDto.getImages();
            wmNews.setImages(imageHreadList.get(0));
            saveWmNewsMaterial(wmNews.getId(),imageHreadList,1);
            imageAllSet.addAll(imageHreadList);
        }else if (type==3){
            //多张图
            imageHreadList = (ArrayList<String>) wmNewsDto.getImages();
            String images = String.join(",",imageHreadList);
            wmNews.setImages(images);
            saveWmNewsMaterial(wmNews.getId(),imageHreadList,1);
            imageAllSet.addAll(imageHreadList);
        }else if (type==-1){
            //自动模式
            if(imageUrlList.size()>=1&&imageUrlList.size()<3){
                //如果大于等于一,小于等于3的按照1张处理
                imageHreadList = imageUrlList.subList(0, 1);
                wmNews.setImages(imageUrlList.get(0));

            }else if(imageUrlList.size()>=3){
                //大于等于3的按照3张处理
                imageHreadList = imageUrlList.subList(0, 3);
                String images = String.join(",",imageHreadList);
                wmNews.setImages(images);
            }
        }



        if (uFlag){
            //是更新就执行更新
            this.updateById(wmNews);
        }else {
            //不是更新就进行保存
            this.save(wmNews);
        }
        //存入中间表数据
        if (imageHreadList!=null){
            saveWmNewsMaterial(wmNews.getId(),imageHreadList,1);
        }
        if (imageUrlList!=null){
            saveWmNewsMaterial(wmNews.getId(),imageUrlList,0);
        }


        wmNewsTaskService.newsToTask(wmNews);
/*
        if (wmNews.getStatus().equals(Short.valueOf("1"))){
            //判断是否是提交提交的话进行数据的审核
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    if (auditNews(textAllList,imageAllSet,wmNews)) {
                        sendToApp(wmNews, wmNewsDto);
                    }

                }
            });
        }*/

    }
    /**
     *
     */

    private void sendToApp(WmNews wmNews, WmNewsDto wmNewsDto) {
        //审核通过就讲存入文章服务
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);
        articleDto.setContent(wmNewsDto.getContent());
        articleDto.setAuthorId(Long.valueOf(wmNews.getUserId()));
        articleDto.setLayout(Short.valueOf(""+wmNews.getType()));
        WmUser user= wmUserService.getById(wmNews.getUserId());
        articleDto.setAuthorName(user.getName());


        WmChannel channel = wmChannelService.getById(wmNewsDto.getChannelId());
        articleDto.setChannelName(channel.getName());
        ResponseResult responseResult = iArticleClient.save(articleDto);
        if(responseResult.getCode()==AppHttpCodeEnum.SUCCESS.getCode()){
            updateStatus(wmNews, WmNews.Status.PUBLISHED, "发送成功");
            //返回的id存入对应的文章id中
            wmNews.setArticleId((Long) responseResult.getData());
            updateById(wmNews);
        }else{
            updateStatus(wmNews, WmNews.Status.ADMIN_AUTH, "转人工");
        }
    }

    @Override
    public Page findList(WmNewsPageReqDto wmNewsPageReqDto) {

        Page<WmNews> wmNewsPage = new Page(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize());
        LambdaQueryWrapper<WmNews> wmNewsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wmNewsLambdaQueryWrapper.eq(wmNewsPageReqDto.getStatus()!=null,WmNews::getStatus,wmNewsPageReqDto.getStatus());
        wmNewsLambdaQueryWrapper.ge(wmNewsPageReqDto.getBeginPubDate()!=null,WmNews::getCreatedTime,wmNewsPageReqDto.getBeginPubDate());
        wmNewsLambdaQueryWrapper.le(wmNewsPageReqDto.getEndPubDate()!=null,WmNews::getCreatedTime,wmNewsPageReqDto.getEndPubDate());
        wmNewsLambdaQueryWrapper.eq(wmNewsPageReqDto.getChannelId()!=null,WmNews::getChannelId,wmNewsPageReqDto.getChannelId());
        wmNewsLambdaQueryWrapper.like(!StringUtils.isBlank(wmNewsPageReqDto.getKeyword()),WmNews::getTitle,wmNewsPageReqDto.getKeyword());
        wmNewsLambdaQueryWrapper.orderByDesc(WmNews::getCreatedTime);

        this.page(wmNewsPage,wmNewsLambdaQueryWrapper);
        return wmNewsPage;
    }

    @Override
    @Transactional
    public ResponseResult delNews(Integer id) {
        if (id==null){
            return ResponseResult.errorResult(501,"文章id不可缺少");
        }
        WmNews byId = this.getById(id);
        if (byId==null){
            return ResponseResult.errorResult(1002,"文章不存在");
        }

        Date date = new Date();
        Date publishTime = byId.getPublishTime();
        if (publishTime.before(date)){
            if (byId.getEnable()==1){
                return ResponseResult.errorResult(501,"文章已上架不能删除");
            }
        }


        this.removeById(id);
        LambdaUpdateWrapper<WmNewsMaterial> wmNewsMaterialLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        wmNewsMaterialLambdaUpdateWrapper.eq(WmNewsMaterial::getNewsId,id);
        wmNewsMaterialService.remove(wmNewsMaterialLambdaUpdateWrapper);
        return ResponseResult.okResult("操作成功");
    }

    @Override
    @Transactional
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        if (wmNewsDto.getId()==null){
            return ResponseResult.errorResult(501,"文章id不可缺少");
        }
        WmNews byId = this.getById(wmNewsDto.getId());
        if (byId==null){
            return ResponseResult.errorResult(1002,"文章不存在");
        }
        Date date = new Date();
        Date publishTime = byId.getPublishTime();
        if (publishTime!=null){

            if (publishTime.after(date)){
                return ResponseResult.okResult(501,"当前文章不在发布状态,不能上下架");
            }
        }
        byId.setEnable(wmNewsDto.getEnable().shortValue());

        this.updateById(byId);

        log.info("发送信息");
        Map<String, String> downOrUpArticle = new HashMap<>();
        downOrUpArticle.put("articleId",""+getById(wmNewsDto.getId()));
        downOrUpArticle.put("status",""+wmNewsDto.getEnable().shortValue());
        kafkaTemplate.send("downOrUpArticle", JSON.toJSONString(downOrUpArticle));
        log.info("发送完成信息");

        return ResponseResult.okResult("成功");
    }

    /**
     * 此方法是存储中间表
     *
     */
    private void saveWmNewsMaterial(Integer newsId,List<String> imageList,int type){
        if (!imageList.isEmpty()) {
            //先去查出来图片对象来
            LambdaQueryWrapper<WmMaterial> wmMaterialLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wmMaterialLambdaQueryWrapper.in(WmMaterial::getUrl,imageList);
            List<WmMaterial> wmMaterialList = wmMaterialService.list(wmMaterialLambdaQueryWrapper);

            //组装WmNewsMaterial对象
            ArrayList<WmNewsMaterial> wmNewsMaterials = new ArrayList<>();
            int order = 0;
            for (WmMaterial wmMaterial : wmMaterialList) {
                WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
                wmNewsMaterial.setOrd(order);
                wmNewsMaterial.setType(type);
                wmNewsMaterial.setNewsId(newsId);
                wmNewsMaterial.setMaterialId(wmMaterial.getId());
                wmNewsMaterials.add(wmNewsMaterial);
            }
            //保存所有数据
            wmNewsMaterialService.saveBatch(wmNewsMaterials);
        }
    }


    /**
     * 审核用户上传的内容
     */
    private boolean auditNews(List<String> textAllList,Set<String> imagesAllSet,WmNews wmNews){
        try {
            //先去图片去提取文字
            //根据imageUrl去下载图片
            List<byte[]> imageList = null;
            if (!imagesAllSet.isEmpty()){
                imageList = imagesAllSet.stream().map(imageUrl -> {
                    byte[] bytes = fileStorageService.downLoadFile(imageUrl);
                    return bytes;
                }).collect(Collectors.toList());
                for (byte[] bytes : imageList) {
                    //根据谷歌算法去提取文字
                    String picText = getPicText(bytes);
                    //将图片文本与之前集合合并
                    textAllList.add(picText);
                }
            }
            //字符串集合转字符串
            String allText=String.join("",textAllList);
            //先去本地敏感词审查
            if (!auditTextByLocal(wmNews,allText)){
                //没通过
                return false;
            }
            //阿里审核
/*         //如果验证全部通过就进行阿里验证
            if (!auditTextByAli(wmNews,allText)){
                //没通过
                return false;
            }
            if (!imageList.isEmpty()&&!auditImageByAli(wmNews,imageList)){
                //如果为空就不会进第二个方法
                //没过
                return false;
            }*/

        } catch (Exception e) {
            e.printStackTrace();
            updateStatus(wmNews, WmNews.Status.FAIL, "审核失败");
            return false;
        }
        //审核通过
        updateStatus(wmNews,WmNews.Status.SUCCESS, "审核通过");

        return true;

    }
    /**
     * 图片获取文本
     */
    private String getPicText(byte[] bytes) throws IOException, TesseractException {
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        BufferedImage imageFile = ImageIO.read(in);
        String result = tess4jClient.doOCR(imageFile);
        return  result;
    }

    /**
     * 本地验证敏感词
     */
    private boolean auditTextByLocal(WmNews wmNews,String allText){

        Set<String> wmSensitiveset = cacheService.scan(WemediaConstants.CATCH_KEY_SENSITIVE);
        if (wmSensitiveset.isEmpty()){
            List<WmSensitive> wmSensitiveList = wmSensitiveMapper.selectList(null);
            List<String> sensitivesList = wmSensitiveList.stream().map(wmSensitive -> {
                String sensitives = wmSensitive.getSensitives();
                return sensitives;
            }).collect(Collectors.toList());
             String[] sensitives =new String[sensitivesList.size()];

            for (int i = 0; i < sensitives.length; i++) {
                sensitives[i] = sensitivesList.get(i);
            }
            cacheService.sAdd(WemediaConstants.CATCH_KEY_SENSITIVE,sensitives);
            wmSensitiveset.addAll(sensitivesList);
        }
        SensitiveWordUtil.initMap(wmSensitiveset);
        Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(allText);
        if (!stringIntegerMap.isEmpty()){
            updateStatus(wmNews, WmNews.Status.FAIL, "审核失败");
            return false;
        }
        return true;
    }

    /**
     * 从阿里去审核图片
     */
    private boolean auditImageByAli(WmNews wmNews, List<byte[]> imageList) throws Exception {
        Map inagesResultMap = greenImageScan.imageScan(imageList);
        String inagesSuggestion = (String) inagesResultMap.get("suggestion");
        if(inagesSuggestion.equals("review")){
            wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode().shortValue());
            wmNews.setReason("人工审核");
            return false;
        }else if (inagesSuggestion.equals("block")){
            wmNews.setStatus(WmNews.Status.FAIL.getCode().shortValue());
            wmNews.setReason("审核失败");
            return false;
        }
        return true;
    }

    /**
     * 去阿里云审核文本
     */
    private boolean auditTextByAli(WmNews wmNews, String textAll) throws Exception {
        Map textResultMap = greenTextScan.greeTextScan(textAll);
        String suggestion = (String) textResultMap.get("suggestion");
        if(suggestion.equals("review")){
            updateStatus(wmNews, WmNews.Status.ADMIN_AUTH, "人工审核");
            return false;
        }else if (suggestion.equals("block")){
            updateStatus(wmNews, WmNews.Status.FAIL, "审核失败");
            return false;
        }
        return true;
    }

    /**
     * 更新news的状态
     */
    private void updateStatus(WmNews wmNews, WmNews.Status fail, String reason) {
        wmNews.setStatus(fail.getCode().shortValue());
        wmNews.setReason(reason);
        this.updateById(wmNews);
    }



}
